package com.nutrition.health.service.impl;

import com.nutrition.health.model.User;
import com.nutrition.health.model.UserHealthProfile;
import com.nutrition.health.model.UserHealthProfileDTO;
import com.nutrition.health.model.UserHealthProfile.ActivityLevel;
import com.nutrition.health.model.UserHealthProfile.Gender;
import com.nutrition.health.model.UserHealthProfile.Goal;
import com.nutrition.health.repository.UserHealthProfileRepository;
import com.nutrition.health.repository.UserRepository;
import com.nutrition.health.service.UserHealthProfileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.Period;
import java.util.*;
import java.util.List;

@Service
@Transactional
public class UserHealthProfileServiceImpl implements UserHealthProfileService {

    private final UserHealthProfileRepository profileRepository;
    private final UserRepository userRepository;

    @Autowired
    public UserHealthProfileServiceImpl(UserHealthProfileRepository profileRepository, UserRepository userRepository) {
        this.profileRepository = profileRepository;
        this.userRepository = userRepository;
    }

    @Override
    public Optional<UserHealthProfile> getProfileByUserId(Long userId) {
        System.out.println("查询用户健康档案，userId: " + userId);
        Optional<UserHealthProfile> profile = profileRepository.findByUserId(userId);
        System.out.println("查询结果: " + (profile.isPresent() ? "找到记录" : "未找到记录"));
        if (profile.isPresent()) {
            System.out.println("记录ID: " + profile.get().getId());
            System.out.println("记录关联的用户ID: " + profile.get().getUserId());
        } else {
            // 尝试直接通过ID查询所有记录，看看是否有数据
            System.out.println("尝试列出所有健康档案记录:");
            List<UserHealthProfile> allProfiles = profileRepository.findAllProfiles();
            System.out.println("总记录数: " + allProfiles.size());
            for (UserHealthProfile p : allProfiles) {
                System.out.println("记录ID: " + p.getId() + ", 用户ID: " + p.getUserId());
            }
        }
        return profile;
    }
    
    @Override
    public Optional<UserHealthProfileDTO> getProfileWithUserInfo(Long userId) {
        System.out.println("查询用户健康档案及用户信息，userId: " + userId);
        
        // 获取健康档案
        Optional<UserHealthProfile> profileOpt = profileRepository.findByUserId(userId);
        if (!profileOpt.isPresent()) {
            System.out.println("未找到用户健康档案");
            return Optional.empty();
        }
        
        // 获取用户信息
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            System.out.println("未找到用户信息");
            return Optional.empty();
        }
        
        // 创建并返回DTO
        UserHealthProfileDTO dto = new UserHealthProfileDTO();
        dto.setHealthProfile(profileOpt.get());
        dto.setUser(userOpt.get());
        
        return Optional.of(dto);
    }

    @Override
    public UserHealthProfile createProfile(Long userId, UserHealthProfile profile) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + userId));

        // 检查用户是否已有健康档案
        Optional<UserHealthProfile> existingProfile = profileRepository.findByUserId(userId);
        if (existingProfile.isPresent()) {
            // 如果已有健康档案，则更新现有档案而不是创建新的
            UserHealthProfile existingProfileData = existingProfile.get();
            existingProfileData.setDateOfBirth(profile.getDateOfBirth());
            existingProfileData.setGender(profile.getGender());
            existingProfileData.setHeight(profile.getHeight());
            existingProfileData.setWeight(profile.getWeight());
            existingProfileData.setTargetWeight(profile.getTargetWeight());
            existingProfileData.setActivityLevel(profile.getActivityLevel());
            existingProfileData.setGoal(profile.getGoal());
            existingProfileData.setHealthConditions(profile.getHealthConditions());
            existingProfileData.setDietaryRestrictions(profile.getDietaryRestrictions());
            return profileRepository.save(existingProfileData);
        }

        // 如果没有健康档案，则创建新的
        profile.setUserId(userId);
        return profileRepository.save(profile);
    }

    @Override
    public UserHealthProfile updateProfile(Long userId, UserHealthProfile profileDetails) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        profile.setDateOfBirth(profileDetails.getDateOfBirth());
        profile.setGender(profileDetails.getGender());
        profile.setHeight(profileDetails.getHeight());
        profile.setWeight(profileDetails.getWeight());
        profile.setTargetWeight(profileDetails.getTargetWeight());
        profile.setActivityLevel(profileDetails.getActivityLevel());
        profile.setGoal(profileDetails.getGoal());
        profile.setHealthConditions(profileDetails.getHealthConditions());
        profile.setDietaryRestrictions(profileDetails.getDietaryRestrictions());

        return profileRepository.save(profile);
    }

    @Override
    public void deleteProfile(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        profileRepository.delete(profile);
    }

    @Override
    public double calculateBMR(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        int age = Period.between(profile.getDateOfBirth(), LocalDate.now()).getYears();
        double weight = profile.getWeight(); // 公斤
        double height = profile.getHeight(); // 厘米
        Gender gender = profile.getGender();

        // 使用修正的Harris-Benedict公式计算BMR
        if (gender == Gender.MALE) {
            return 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age);
        } else {
            return 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age);
        }
    }

    @Override
    public double calculateDailyCalorieNeeds(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        double bmr = calculateBMR(userId);
        ActivityLevel activityLevel = profile.getActivityLevel();
        Goal goal = profile.getGoal();

        // 根据活动水平计算每日能量消耗
        double activityMultiplier;
        switch (activityLevel) {
            case SEDENTARY:
                activityMultiplier = 1.2;
                break;
            case LIGHTLY_ACTIVE:
                activityMultiplier = 1.375;
                break;
            case MODERATELY_ACTIVE:
                activityMultiplier = 1.55;
                break;
            case VERY_ACTIVE:
                activityMultiplier = 1.725;
                break;
            case EXTREMELY_ACTIVE:
                activityMultiplier = 1.9;
                break;
            default:
                activityMultiplier = 1.2;
        }

        double tdee = bmr * activityMultiplier; // 每日总能量消耗

        // 根据目标调整卡路里需求
        switch (goal) {
            case LOSE_WEIGHT:
                return tdee - 500; // 每天减少500卡路里，大约每周减少0.5公斤
            case GAIN_WEIGHT:
            case BUILD_MUSCLE:
                return tdee + 500; // 每天增加500卡路里，大约每周增加0.5公斤
            case MAINTAIN_WEIGHT:
            case IMPROVE_HEALTH:
            default:
                return tdee;
        }
    }

    @Override
    public double calculateBMI(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        double weightKg = profile.getWeight();
        double heightM = profile.getHeight() / 100.0; // 转换为米

        return weightKg / (heightM * heightM);
    }

    @Override
    public String getBMICategory(Long userId) {
        double bmi = calculateBMI(userId);

        if (bmi < 18.5) {
            return "体重过轻";
        } else if (bmi < 24.0) {
            return "正常体重";
        } else if (bmi < 28.0) {
            return "超重";
        } else if (bmi < 30.0) {
            return "轻度肥胖";
        } else if (bmi < 40.0) {
            return "中度肥胖";
        } else {
            return "重度肥胖";
        }
    }

    @Override
    public Map<String, Double> generateNutrientRequirements(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        double calorieNeeds = calculateDailyCalorieNeeds(userId);
        int age = Period.between(profile.getDateOfBirth(), LocalDate.now()).getYears();
        Gender gender = profile.getGender();
        Goal goal = profile.getGoal();

        Map<String, Double> requirements = new HashMap<>();

        // 卡路里
        requirements.put("calories", calorieNeeds);

        // 蛋白质（克）- 根据体重和目标调整
        double proteinPerKg;
        switch (goal) {
            case BUILD_MUSCLE:
                proteinPerKg = 2.0; // 增肌需要更多蛋白质
                break;
            case LOSE_WEIGHT:
                proteinPerKg = 1.6; // 减重时保持较高蛋白质摄入以保持肌肉
                break;
            default:
                proteinPerKg = 1.2; // 一般推荐
        }
        requirements.put("protein", profile.getWeight() * proteinPerKg);

        // 碳水化合物（克）- 占总卡路里的45-65%
        double carbPercentage;
        switch (goal) {
            case BUILD_MUSCLE:
                carbPercentage = 0.55; // 55%
                break;
            case LOSE_WEIGHT:
                carbPercentage = 0.40; // 40%
                break;
            default:
                carbPercentage = 0.50; // 50%
        }
        requirements.put("carbohydrates", (calorieNeeds * carbPercentage) / 4); // 每克碳水4卡路里

        // 脂肪（克）- 占总卡路里的20-35%
        double fatPercentage = 1 - carbPercentage - (requirements.get("protein") * 4 / calorieNeeds);
        requirements.put("fat", (calorieNeeds * fatPercentage) / 9); // 每克脂肪9卡路里

        // 纤维（克）
        requirements.put("fiber", gender == Gender.MALE ? 38.0 : 25.0);

        // 水（毫升）
        requirements.put("water", profile.getWeight() * 30); // 每公斤体重30毫升

        // 其他微量营养素
        if (age <= 30) {
            requirements.put("calcium", 1000.0); // 毫克
        } else {
            requirements.put("calcium", 1200.0); // 毫克
        }

        requirements.put("iron", gender == Gender.MALE ? 8.0 : 18.0); // 毫克
        requirements.put("vitamin_c", 75.0); // 毫克
        requirements.put("vitamin_d", 15.0); // 微克

        return requirements;
    }

    @Override
    public Map<String, String> generateHealthRecommendations(Long userId) {
        UserHealthProfile profile = profileRepository.findByUserId(userId)
                .orElseThrow(() -> new RuntimeException("Health profile not found for user id: " + userId));

        Map<String, String> recommendations = new HashMap<>();

        // 获取BMI分类
        String bmiCategory = getBMICategory(userId);

        // 根据BMI提供建议
        if (bmiCategory.equals("体重过轻")) {
            recommendations.put("weight", "您的BMI指数偏低，建议适当增加热量摄入，增加优质蛋白质的摄入，如瘦肉、鱼、蛋、奶制品等。");
        } else if (bmiCategory.equals("超重") || bmiCategory.contains("肥胖")) {
            recommendations.put("weight", "您的BMI指数偏高，建议控制热量摄入，增加身体活动，选择低热量高营养的食物，如蔬菜、水果、全谷物等。");
        } else {
            recommendations.put("weight", "您的BMI指数在正常范围内，建议保持均衡饮食和适当的身体活动。");
        }

        // 根据活动水平提供建议
        ActivityLevel activityLevel = profile.getActivityLevel();
        if (activityLevel == ActivityLevel.SEDENTARY || activityLevel == ActivityLevel.LIGHTLY_ACTIVE) {
            recommendations.put("activity", "您的活动水平较低，建议增加日常活动，如步行、爬楼梯等，每周进行至少150分钟的中等强度有氧运动。");
        } else {
            recommendations.put("activity", "您保持着良好的活动水平，建议继续保持，并确保运动种类多样化，包括有氧运动、力量训练和柔韧性练习。");
        }

        // 根据目标提供建议
        Goal goal = profile.getGoal();
        switch (goal) {
            case LOSE_WEIGHT:
                recommendations.put("diet", "建议控制热量摄入，增加蛋白质比例，减少精制碳水化合物和添加糖的摄入，多吃蔬菜水果，保持适当的运动。");
                break;
            case GAIN_WEIGHT:
                recommendations.put("diet", "建议增加热量摄入，增加优质蛋白质、健康脂肪和复合碳水化合物的摄入，进行力量训练以促进肌肉生长。");
                break;
            case BUILD_MUSCLE:
                recommendations.put("diet", "建议增加蛋白质摄入，保证足够的碳水化合物供能，进行规律的力量训练，确保充分休息和恢复。");
                break;
            case IMPROVE_HEALTH:
                recommendations.put("diet", "建议均衡饮食，多样化食物选择，增加蔬菜水果摄入，减少加工食品和添加糖的摄入，保持适当的身体活动。");
                break;
            default:
                recommendations.put("diet", "建议均衡饮食，保持适当的身体活动，确保充足的睡眠和水分摄入。");
        }

        // 根据健康状况提供建议
        String healthConditions = profile.getHealthConditions();
        if (healthConditions != null && !healthConditions.isEmpty()) {
            if (healthConditions.toLowerCase().contains("diabetes") || healthConditions.toLowerCase().contains("糖尿病")) {
                recommendations.put("health_condition", "对于糖尿病患者，建议控制碳水化合物摄入，选择低血糖指数的食物，规律进餐，避免过度饥饿或过饱。");
            } else if (healthConditions.toLowerCase().contains("hypertension") || healthConditions.toLowerCase().contains("高血压")) {
                recommendations.put("health_condition", "对于高血压患者，建议减少钠盐摄入，增加钾的摄入，保持健康体重，限制酒精摄入，戒烟。");
            } else {
                recommendations.put("health_condition", "根据您的健康状况，建议咨询医生获取更具体的饮食和生活方式建议。");
            }
        }

        // 根据饮食限制提供建议
        String dietaryRestrictions = profile.getDietaryRestrictions();
        if (dietaryRestrictions != null && !dietaryRestrictions.isEmpty()) {
            if (dietaryRestrictions.toLowerCase().contains("vegetarian") || dietaryRestrictions.toLowerCase().contains("素食")) {
                recommendations.put("dietary_restriction", "对于素食者，建议确保摄入足够的蛋白质（豆类、豆腐、坚果等），以及维生素B12、铁、锌、钙等营养素。");
            } else if (dietaryRestrictions.toLowerCase().contains("lactose") || dietaryRestrictions.toLowerCase().contains("乳糖")) {
                recommendations.put("dietary_restriction", "对于乳糖不耐受者，建议选择无乳糖奶制品或植物奶，确保从其他食物中获取足够的钙。");
            } else if (dietaryRestrictions.toLowerCase().contains("gluten") || dietaryRestrictions.toLowerCase().contains("麸质")) {
                recommendations.put("dietary_restriction", "对于麸质不耐受者，建议选择天然无麸质食物，如米、玉米、马铃薯、豆类等，避免小麦、大麦、黑麦等含麸质食物。");
            } else {
                recommendations.put("dietary_restriction", "根据您的饮食限制，建议咨询营养师获取更具体的饮食建议。");
            }
        }

        // 通用建议
        recommendations.put("general", "保持充足的水分摄入，每天至少8杯水；确保充足的睡眠，成年人每天7-9小时；减少加工食品和添加糖的摄入；增加蔬菜水果摄入，每天至少5份。");

        return recommendations;
    }

    @Override
    public Map<String, Object> generateDietPlan(Long userId) {
        // 获取用户的营养需求
        Map<String, Double> nutrientRequirements = generateNutrientRequirements(userId);

        // 创建饮食计划
        Map<String, Object> dietPlan = new HashMap<>();

        // 添加营养摄入目标
        dietPlan.put("nutrientTargets", nutrientRequirements);

        // 创建每日餐食计划
        Map<String, List<Map<String, Object>>> mealPlan = new HashMap<>();

        // 早餐（约占总卡路里的25%）
        List<Map<String, Object>> breakfast = new ArrayList<>();
        breakfast.add(createMealItem("全麦面包", 2, "片", 160.0));
        breakfast.add(createMealItem("鸡蛋", 2, "个", 140.0));
        breakfast.add(createMealItem("牛奶", 1, "杯", 120.0));
        breakfast.add(createMealItem("蓝莓", 1, "杯", 80.0));
        mealPlan.put("breakfast", breakfast);

        // 午餐（约占总卡路里的30%）
        List<Map<String, Object>> lunch = new ArrayList<>();
        lunch.add(createMealItem("糙米", 1, "杯", 220.0));
        lunch.add(createMealItem("鸡胸肉", 100, "克", 165.0));
        lunch.add(createMealItem("混合蔬菜", 2, "杯", 100.0));
        lunch.add(createMealItem("橄榄油", 1, "茶匙", 40.0));
        mealPlan.put("lunch", lunch);

        // 晚餐（约占总卡路里的30%）
        List<Map<String, Object>> dinner = new ArrayList<>();
        dinner.add(createMealItem("三文鱼", 150, "克", 280.0));
        dinner.add(createMealItem("红薯", 1, "中等", 115.0));
        dinner.add(createMealItem("西兰花", 2, "杯", 60.0));
        dinner.add(createMealItem("橄榄油", 1, "茶匙", 40.0));
        mealPlan.put("dinner", dinner);

        // 零食（约占总卡路里的15%）
        List<Map<String, Object>> snacks = new ArrayList<>();
        snacks.add(createMealItem("希腊酸奶", 1, "杯", 150.0));
        snacks.add(createMealItem("杏仁", 30, "克", 180.0));
        snacks.add(createMealItem("苹果", 1, "个", 80.0));
        mealPlan.put("snacks", snacks);

        dietPlan.put("mealPlan", mealPlan);

        // 添加饮食建议
        List<String> dietaryTips = new ArrayList<>();
        dietaryTips.add("保持规律进餐，避免过度饥饿。");
        dietaryTips.add("细嚼慢咽，享受食物的味道。");
        dietaryTips.add("选择全食物，减少加工食品。");
        dietaryTips.add("控制食物的份量，避免过量。");
        dietaryTips.add("保持充足的水分摄入，每天至少8杯水。");
        dietPlan.put("dietaryTips", dietaryTips);

        return dietPlan;
    }

    // 辅助方法：创建餐食项
    private Map<String, Object> createMealItem(String name, double quantity, String unit, double calories) {
        Map<String, Object> item = new HashMap<>();
        item.put("name", name);
        item.put("quantity", quantity);
        item.put("unit", unit);
        item.put("calories", calories);
        return item;
    }
}